/*
    Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com)

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version
    3 of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "logentry.h"

bool  gMask    = true;

//LogEntry
LogEntry::LogEntry() {
}

LogEntry::LogEntry(std::string& entry) {
    parse_ok = parse(entry);

}

bool LogEntry::successful() {

	return (status_hit == "HIT");

}

const char* months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug" , "Sep", "Oct", "Nov", "Dec" };
Regex entry_start("([0-9]+)([\\.])([0-9]+)([\\ ]+)([0-9]+)([\\ ]+)([0-9\\.]+)([\\ ]+)([A-Z]+|TCP_IMS|TCP_REFRESH|TCP_MEM)([_])([A-Z]+)([\\/])([0-9]+)([\\ ]+)([0-9]+)([\\ ]+)([A-Z\\_]+)([\\ ]+)(.+)( - )([A-Za-z0-9\\-\\_\\/\\.]+)([\\ ]+)([\\-\\/A-z]+)");
Regex hostname_parts("([^.]+)(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?$");


std::string LogEntry::maskHostname(std::string hostname) {

    std::vector<std::string> parts;
    hostname_parts.match(hostname, &parts);

    //if only 1-2 parts, or 3 parts and a 2 character suffix, pass through unchanged
    if(parts.size()<=2 || parts.size()==3 && parts[parts.size()-1].size()==2) return hostname;

    int num = atoi(parts[parts.size()-1].c_str());

    std::string output;

    //if last element is numeric, assume it is a numbered ip address
    //(ie 192.168.0.1 => 192.168.0-)
    if(num!=0) {
        for(size_t i=0;i<parts.size()-1;i++) {
            if(i>0) output += '.';
            output += parts[i];
        }

        output += '-';
        return output;
    }

    //hide the first element
    //(ie dhcp113.web.com -> web.com
    for(size_t i=1;i<parts.size();i++) {
            if(i>1) output += '.';
            output += parts[i];
    }

    return output;
}


//parse apache access.log entry into components
int LogEntry::parse(std::string& line) {

    std::vector<std::string> matches;
    entry_start.match(line, &matches);

    printf(".");

/*
    printf("====\nMathes: %d\n",   matches.size());

    for(int i=0;i<matches.size();i++) {
    	printf("#%d: '%s'\n", i, matches[i].c_str()); }
*/
    if( matches.size() != 23 ) {

    	printf("\nLE Incorrect line: %s", line.c_str());
    	return 0;

    }

    status_hit      = matches[10].c_str();       // HIT/MISS
    request_from_ip = matches[6].c_str();  // Client IP
    request_to_ip   = matches[20].c_str(); // Direct TO
    request_url     = matches[18].c_str();       // URL
    timestamp = atoi( matches[0].c_str() );     // Timstamp
    response_content_type    = matches[22].c_str();  // Content Type
    response_code   = atoi(matches[12].c_str());     // Code
    response_bytes  = atol(matches[14].c_str());     // Byte Response
    response_bytess = matches[14].c_str();

    dump_status  = "Status: " + matches[10] + "/" + matches[12];
    dump_time    = "Time: " + matches[0] + matches[1] + matches[2];
    dump_request = "Request size: " + matches[4] + " bytes / Response size: " + matches[14] + " bytes";
    dump_ip      = "From IP: " + matches[6] + " -> To IP: " + matches[20];
    dump_url     = "URL: (" + matches[16] + ") " + matches[18];
    dump_content = "Content: " + matches[22];

    return 1;
}

bool LogEntry::parsedOK() {
    return parse_ok;
}

int         LogEntry::responseCode()    { return response_code; }
long        LogEntry::responseBytes()   { return response_bytes; }
std::string LogEntry::responseBytesS()  { return response_bytess; }
long        LogEntry::getTimestamp()    { return timestamp; }

std::string LogEntry::responseContentType() { return response_content_type; }
std::string LogEntry::requestURL()          { return request_url; }
std::string LogEntry::requestFromIp()       { return request_from_ip; }
std::string LogEntry::requestToIp()         { return request_to_ip; }
